#include "modbushandler.h"
#include <QDebug>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QFileInfo>
#include <QCoreApplication>
#include "qmessagebox.h"

#define ENERGY_FILE (QCoreApplication::applicationDirPath() + "/energy_data.json" ) // 数据文件名


ModbusHandler::ModbusHandler(QObject *parent) : QObject(parent)
{
    connect(&serial, &QSerialPort::readyRead, this, &ModbusHandler::handleReadyRead);
}

void ModbusHandler::connectToPort(const QString &portName)
{

    serial.setPortName(portName);
    serial.setBaudRate(baudRate);
    serial.setDataBits(QSerialPort::Data8);
    serial.setParity(QSerialPort::NoParity);
    serial.setStopBits(QSerialPort::OneStop);
    serial.setFlowControl(QSerialPort::NoFlowControl);

    if (!serial.open(QIODevice::ReadWrite)) {
        qDebug() << "Failed to open port:" << serial.errorString();
       QMessageBox::information(nullptr, "错误", "缺少端口信息");
    } else {
        qDebug() << "Serial port opened.";
    }
}

void ModbusHandler::readAllRegisters()
{
    responseBuffer.clear();

    QByteArray request;
    request.append(static_cast<char>(0x01));  // 设备地址
    request.append(static_cast<char>(0x03));  // 功能码 - 读取保持寄存器
    request.append(static_cast<char>(0x00));  // 起始地址高字节
    request.append(static_cast<char>(0x00));  // 起始地址低字节
    request.append(static_cast<char>(0x00));  // 读取长度高字节
    request.append(static_cast<char>(0x32));  // 读取长度 - 50个寄存器 (覆盖标称容量~单体16电压)
    quint16 crc = calculateCRC(request);
    request.append(static_cast<char>(crc & 0xFF));          // CRC低位
    request.append(static_cast<char>((crc >> 8) & 0xFF));   // CRC高位
    qDebug() << "Request Frame:" << request.toHex();
    serial.write(request);
}

void ModbusHandler::handleReadyRead()
{
    responseBuffer += serial.readAll();
    qDebug() << "responseBuffer:" << responseBuffer.toHex();
    if (responseBuffer.size() < 5) return;  // 最短应答长度检查
    int dataLength = static_cast<quint8>(responseBuffer[2]);
    int expectedLength = 3 + dataLength + 2;  // 地址+功能码+长度+数据+CRC
    if (responseBuffer.size() < expectedLength) return;
    quint16 crcReceived = (static_cast<quint8>(responseBuffer[expectedLength - 1]) << 8) |
                          static_cast<quint8>(responseBuffer[expectedLength - 2]);
    QByteArray data = responseBuffer.left(expectedLength - 2);
    quint16 crcCalculated = calculateCRC(data);
    if (crcReceived != crcCalculated) {
        qDebug() << "CRC Error!";
        responseBuffer.clear();
        return;
    }
    auto readU16 = [&](int offset) -> quint16 {
        return (static_cast<quint8>(responseBuffer[offset]) << 8) |
               static_cast<quint8>(responseBuffer[offset+1]);
    };
    double ratedCapacity=readU16(5) * 0.1;          // 标称容量
    qDebug()<<"readU16(5)="<<int(responseBuffer[5]);
    int cellCount =readU16(7);
    double totalVoltage = readU16(9) * 0.1;      // 总电压
    double totalCurrent = static_cast<qint16>(readU16(11)) * 0.1;  // 总电流，带符号
    int soc = readU16(13);                       // SOC
    int soh = readU16(15)*0.1;                       // SOH
    int cycleCount=readU16(17);
    quint16 protectionFlags1 = readU16(19);  // 保护标志1
    quint16 protectionFlags2 = readU16(21);  // 保护标志2
    double temperatures[6];
    for (int i = 0; i < 6; ++i) {
        temperatures[i] = static_cast<qint16>(readU16(47 + i * 2));
    }
    double cellVoltages[16];
    for (int i = 0; i < 16; ++i) {
        cellVoltages[i] = readU16(69 + i * 2) * 1.0;  // 单体电压(mV)
    }
    emit dataRead(totalVoltage, totalCurrent, soc, soh, temperatures,
                  cellVoltages, protectionFlags1, protectionFlags2,
                  ratedCapacity,cellCount,cycleCount);
    QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
    emit dataCollected(timestamp,totalVoltage, totalCurrent, soc, soh, temperatures,
                       cellVoltages, protectionFlags1, protectionFlags2,
                       ratedCapacity,cellCount,cycleCount);
    qDebug() <<"cellCount:"<<cellCount;

    //增加电量计算

    calculateEnergy(totalCurrent);// 计算电量




    responseBuffer.clear();
}

void ModbusHandler::handleTimeout()
{
    qDebug() << "Modbus response timeout!";
    responseBuffer.clear();
}

quint16 ModbusHandler::calculateCRC(const QByteArray &data)
{
    quint16 crc = 0xFFFF;
    for (char byte : data) {
        crc ^= static_cast<quint8>(byte);
        for (int i = 0; i < 8; ++i) {
            if (crc & 0x0001) {
                crc >>= 1;
                crc ^= 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    return crc;
}
void ModbusHandler::setBaudRate(int rate)
{
    baudRate = rate;
}
void ModbusHandler::disconnectPort()
{
    if (serial.isOpen()) {
        serial.close();
        qDebug() << "Serial port closed.";
    }
}

bool ModbusHandler::isPortOpen() const
{
    return serial.isOpen();
}

void ModbusHandler::calculateEnergy(double current)
{
    if (!lastUpdateTime.isValid()) {
        lastUpdateTime = QDateTime::currentDateTime();
        return;  // 第一次读取时跳过计算
    }

    // 计算时间差（单位：小时）
    QDateTime now = QDateTime::currentDateTime();
    double deltaTime = lastUpdateTime.msecsTo(now) / 3600000.0;  // 毫秒转小时
    lastUpdateTime = now;

    // 根据电流正负计算电量
    if (current > 0) {
        totalChargeAh += current * deltaTime;
    } else if (current < 0) {
        totalDischargeAh += -current * deltaTime;
    }

    // 发射信号通知主窗口更新
    emit energyUpdated(totalChargeAh, totalDischargeAh);
}
void ModbusHandler::clearEnergy()
{
    totalChargeAh = 0.0;
    totalDischargeAh = 0.0;
    emit energyUpdated(totalChargeAh, totalDischargeAh);  // 立即更新显示
}
void ModbusHandler::loadEnergyData()
{
    QFile file(ENERGY_FILE);
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "⚠️ 无电量数据文件，电量初始化为0";
        totalChargeAh = 0.0;
        totalDischargeAh = 0.0;
        return;
    }

    QByteArray fileData = file.readAll();
    QJsonDocument doc = QJsonDocument::fromJson(fileData);
    QJsonObject obj = doc.object();

    totalChargeAh = obj.value("chargeAh").toDouble();
    totalDischargeAh = obj.value("dischargeAh").toDouble();

    qDebug() << "✅ 电量数据读取成功："
             << "充电量:" << totalChargeAh << "Ah"
             << "放电量:" << totalDischargeAh << "Ah";
}

// 保存电量数据
void ModbusHandler::saveEnergyData()
{
    QJsonObject obj;
    obj["chargeAh"] = totalChargeAh;
    obj["dischargeAh"] = totalDischargeAh;

    QJsonDocument doc(obj);

    QFile file(ENERGY_FILE);
    qDebug() << "📁 保存路径：" << QFileInfo(file).absoluteFilePath();
    if (!file.open(QIODevice::WriteOnly)) {
        qWarning() << "❌ 保存电量数据失败";
        return;
    }

    file.write(doc.toJson());
    file.close();

    qDebug() << "✅ 电量数据已保存";
}
